package yunjiao.javatutorials.guava.concurrent.interrupt;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 优雅的服务关闭
 *
 * @author yangyunjiao
 */
public class GracefulShutdownService {
    private final Lock lock = new ReentrantLock();
    private final InterruptAwareCondition shutdownCondition;
    private volatile boolean shutdownRequested = false;
    private final List<Thread> workerThreads = new ArrayList<>();

    public GracefulShutdownService() {
        this.shutdownCondition = new InterruptAwareCondition(lock.newCondition());
    }

    public void start() {
        // 启动工作线程
        for (int i = 0; i < 3; i++) {
            Thread worker = new WorkerThread("Worker-" + i, shutdownCondition, lock);
            workerThreads.add(worker);
            worker.start();
        }
        System.out.println("服务已启动，运行 3 个工作线程");
    }

    public void shutdown() {
        System.out.println("开始优雅关闭...");
        shutdownRequested = true;

        lock.lock();
        try {
            // 通知所有工作线程关闭
            shutdownCondition.signalAll();
        } finally {
            lock.unlock();
        }

        // 等待工作线程结束
        for (Thread worker : workerThreads) {
            try {
                worker.join(5000); // 最多等待 5 秒
                if (worker.isAlive()) {
                    System.out.println("线程 " + worker.getName() + " 未正常结束，进行中断");
                    worker.interrupt();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("关闭过程被中断");
            }
        }

        // 打印中断统计
        shutdownCondition.printInterruptStatistics();
        System.out.println("服务关闭完成");
    }

    private class WorkerThread extends Thread {
        private final InterruptAwareCondition condition;
        private final Lock workerLock;

        public WorkerThread(String name, InterruptAwareCondition condition, Lock lock) {
            super(name);
            this.condition = condition;
            this.workerLock = lock;
        }

        @Override
        public void run() {
            System.out.println(getName() + ": 开始工作");

            while (!shutdownRequested && !isInterrupted()) {
                workerLock.lock();
                try {
                    // 模拟工作
                    System.out.println(getName() + ": 执行工作任务");

                    // 等待条件或工作周期
                    boolean completed = condition.await(2, TimeUnit.SECONDS);

                    if (condition.wasInterrupted()) {
                        System.out.println(getName() + ": 检测到等待被中断，准备退出");
                        break;
                    }

                    if (shutdownRequested) {
                        System.out.println(getName() + ": 收到关闭信号，准备退出");
                        break;
                    }

                } catch (InterruptedException e) {
                    System.out.println(getName() + ": 被中断，准备退出");
                    break;
                } finally {
                    workerLock.unlock();
                }
            }

            System.out.println(getName() + ": 工作结束");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        GracefulShutdownService service = new GracefulShutdownService();
        service.start();

        // 运行一段时间后关闭
        Thread.sleep(3000);
        service.shutdown();
    }
}
